﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hallenberg.SmartClient.Menu;
using System.Collections.ObjectModel;
using NUnit.Framework;

namespace Hallenberg.SmartClient.Test.Menu
{
    [TestFixture]
    public class MenuManagerTest
    {
        const string STR_MainMenu = "MainMenu";

        [Test]
        public void SmartClient_Menu_MenuManager_Create()
        {
            MenuManager menuManager = new MenuManager();
            menuManager.Create(STR_MainMenu);
            MenuItemContainer menuItemContainer = menuManager.Find(STR_MainMenu, false);

            Assert.That(menuItemContainer, Is.Not.Null);
        }

        [Test]
        public void SmartClient_Menu_MenuManager_Create_PassNull_ExpectFail()
        {
            MenuManager menuManager = new MenuManager();
            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() => menuManager.Create(null));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("menuName"));
        }

        [Test]
        public void SmartClient_Menu_MenuManager_Find_PassNull_ExpectFail()
        {
            MenuManager menuManager = new MenuManager();
            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() => menuManager.Find(null, false));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("menuName"));
        }

        [Test]
        public void SmartClient_Menu_MenuManager_Find_UnknownMenuName_NoFallback_ExpectFail()
        {
            string ExpectedExceptionMessage = "Could not locate menu [NoSuchMenu] and fallback menu manager has not been set";

            MenuManager menuManager = new MenuManager();
            InvalidOperationException exception = Assert.Throws<InvalidOperationException>(() => menuManager.Find("NoSuchMenu", false));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.Message, Is.EqualTo(ExpectedExceptionMessage));

        }

        [Test]
        public void SmartClient_Menu_MenuManager_Find_UnknownMenuName_Expect_Fallback()
        {
            string fallbackMenuName = "TheFallbackMenu";
            MenuManager menuManager = new MenuManager();
            menuManager.SetFallbackMenuManager(new MenuItemContainer(fallbackMenuName));

            MenuItemContainer providedMenuItemContainer = menuManager.Find("NoSuchMenu", false);

            Assert.That(fallbackMenuName, Is.EqualTo(providedMenuItemContainer.MenuItemTitle));
        }

        [Test]
        public void SmartClient_Menu_MenuManager_AllMenuItemContainers()
        {
            const string ContainerOne = "ContainerOne";
            const string ContainerTwo = "ContainerTwo";
            const string ContainerThree = "ContainerThree";

            MenuManager menuManager = new MenuManager();

            menuManager.Create(ContainerOne);
            menuManager.Create(ContainerTwo);
            menuManager.Create(ContainerThree);

            ReadOnlyCollection<MenuItemContainer> allContainers = menuManager.AllMenuItemContainers;

            Assert.That(allContainers.Count, Is.EqualTo(3));
            Assert.That(allContainers.FirstOrDefault(item => item.MenuItemTitle == ContainerOne), Is.Not.Null);
            Assert.That(allContainers.FirstOrDefault(item => item.MenuItemTitle == ContainerTwo), Is.Not.Null);
            Assert.That(allContainers.FirstOrDefault(item => item.MenuItemTitle == ContainerThree), Is.Not.Null);
        }

        [Test]
        public void SmartClient_Menu_MenuManager_GetSelectedMenuItems_PassNull_Param1_ExpectFail()
        {
            MenuManager menuManager = new MenuManager();
            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() => menuManager.GetSelectedMenuItems("SomeCollectionName", null));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("menuItemName"));
        }

        [Test]
        public void SmartClient_Menu_MenuManager_GetSelectedMenuItems_PassNull_Param2_ExpectFail()
        {
            MenuManager menuManager = new MenuManager();

            ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() => menuManager.GetSelectedMenuItems(null, "SomeMenuName"));

            Assert.That(exception, Is.Not.Null);
            Assert.That(exception.ParamName, Is.EqualTo("menuCollectionName"));
        }

        [Test]
        public void SmartClient_Menu_MenuManager_GetSelectedMenuItems()
        {
            const string Option1 = "Option 1";
            const string Option2 = "Option 2";
            const string SubOption1 = "Sub Option 1";
            const string SubOption2 = "Sub Option 2";
            const string LowerOption1 = "Lower Option 1";
            const string LowerOption2 = "Lower Option 2";

            MenuItem miOption1 = new MenuItem(Option1, Option1, "Tooltip 1");
            MenuItem miOption2 = new MenuItem(Option1, Option2, "Tooltip 2");

            MenuItem subOption1 = new MenuItem(SubOption1, SubOption1, "Sub ToolTip 1");
            MenuItem subOption2 = new MenuItem(SubOption2, SubOption2, "Sub ToolTip 2");

            MenuItem lowerOption1 = new MenuItem(LowerOption1, LowerOption1, "Lower ToolTip 1");
            MenuItem lowerOption2 = new MenuItem(LowerOption2, LowerOption2, "Lower ToolTip 2");

            IMenuManager menuManager = new MenuManager();

            MenuItemContainer mainMenuContainer = menuManager.Find(STR_MainMenu, true);
            mainMenuContainer.AddMenuItem(miOption1);
            mainMenuContainer.AddMenuItem(miOption2);

            MenuItemContainer subMenuContainer = menuManager.Find(Option1, true);
            subMenuContainer.AddMenuItem(subOption1);
            subMenuContainer.AddMenuItem(subOption2);

            MenuItemContainer lowerMenuContainer = menuManager.Find(SubOption2, true);
            lowerMenuContainer.AddMenuItem(lowerOption1);
            lowerMenuContainer.AddMenuItem(lowerOption2);

            ReadOnlyCollection<MenuItem> selectedItems = menuManager.GetSelectedMenuItems(SubOption2, LowerOption2);

            Assert.That(selectedItems.Count, Is.EqualTo(3));
            Assert.That(selectedItems.FirstOrDefault(item => item.MenuItemName == Option1), Is.Not.Null);
            Assert.That(selectedItems.FirstOrDefault(item => item.MenuItemName == SubOption2), Is.Not.Null);
            Assert.That(selectedItems.FirstOrDefault(item => item.MenuItemName == LowerOption2), Is.Not.Null);
        }
    }
}
